import {
	computed,
	ref,
	watchEffect
} from "vue";
import {
	camelCase
} from 'lodash-es'

function getDefaultName(key) {
	const str = camelCase(key);
	return `default${str[0].toLocaleUpperCase()+str.slice(1)}`;
}
// eventName is keybase, change -> onChange; visible-change -> onVisibleChange
function getEventPropsName(eventName) {
	const str = camelCase(eventName);
	return `on${str[0].toLocaleUpperCase()}${str.slice(1)}`;
}

/**
 * 受控和非受控逻辑处理，包含 value / modelValue / events
 * @param props 属性
 * @param emit 触发方法，context.emit
 * @param key 受控属性名称
 * @param eventName 事件名称
 * @example const [value, setValue] = useDefault();
 * @returns [value, setValue]
 */
export function useDefault(props, emit, key, eventName) {
	const modelValue = 'modelValue';
	const defaultName = getDefaultName(String(key));
	const isUsedModelValue = props[modelValue] !== undefined;
	const isUsedKey = props[key] !== undefined;

	const innerValue = ref()

	if (isUsedKey) {
		innerValue.value = props[key];
	} else if (isUsedModelValue) {
		innerValue.value = props[modelValue];
	} else {
		innerValue.value = props[defaultName];
	}
	watchEffect(() => {
		if (isUsedModelValue) {
			innerValue.value = props[modelValue];
		}
		if (isUsedKey) {
			innerValue.value = props[key];
		}
	});

	function emitEvents(value, ...arg) {
		const updateKeys = [`update:${key}`];
		if (isUsedModelValue) {
			updateKeys.push(`update:modelValue`);
		}
		// Props Event exists in Vue3. `props.onChange()` is equal `context.emit('change')`
		updateKeys.forEach((updateKey) => {
			emit(updateKey, value, ...arg);
		});
		const propsEventName = getEventPropsName(eventName);
		props[propsEventName]?.(value, ...arg);
	}

	function setInnerValue(value, ...arg) {
		if (!isUsedKey && !isUsedModelValue) {
			innerValue.value = value;
		}
		emitEvents(value, ...arg);
	}

	const innerValueRef = computed({
		get() {
			return innerValue.value;
		},
		set(value) {
			setInnerValue(value);
		},
	});

	return [innerValueRef, setInnerValue];
}